#include "dominion.h"
#include "dominion_helpers.h"
#include <string.h>
#include <getopt.h>
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <math.h>
#include "rngs.h"
#include "interface.h"
#include "coreUnitTestHelpers.h"

int main(){
  int i, j, m, numFailed, expectedFailures, unexpectedFailure, numPlayers, seed;
  int errorSeed, kCardSameSeed, badNumPlayerSeed, kCardOutOfRangeSeed;
  int firstCard, secondCard;
  struct gameState G;
  int k[NUM_K_CARDS];
  numFailed = 0;
  expectedFailures = 0;

  printf("\n***Testing initializeGame()***\n\n");
  /* Conduct 2000 tests */
  for(j = 0; j < 2000; j++){
    unexpectedFailure = 1;
    kCardSameSeed = 0;
    badNumPlayerSeed = 0;
    kCardOutOfRangeSeed = 0;

    /* Make each of these expected failures happen ~10% of the time */
    errorSeed = floor(Random() * 10);
    if(errorSeed == 1){
      kCardSameSeed = 1;
    }
    else if(errorSeed == 2){
      badNumPlayerSeed = 1;
    }
    else if(errorSeed == 3){
      kCardOutOfRangeSeed = 1;
    }

    /* Fill the Game State with garbage */
    for (i = 0; i < sizeof(struct gameState); i++) {
      ((char*)&G)[i] = floor(Random() * 256);
    }

    /* Set number of random players */
    numPlayers = floor(Random() * PLAYER_RANGE) + MIN_PLAYERS;
    /* If the flag is set, make numPlayers (likely) bad */
    if(badNumPlayerSeed == 1){
      numPlayers = floor(Random() * 100); //Gives a good chance that numPlayers won't be valid
    }

    /* Set the seed */
    seed = floor(Random() * 100000);
    
    //kingdom card array initialization.  only uses kingdom cards whose cardEffect() functions have been debugged.
    //to add another, just delete it form the list of || statements below)
    int numSelected = 0;
    
    while(numSelected < NUM_K_CARDS) {
      int used = 0;
      int card = floor(Random() * NUM_TOTAL_K_CARDS);
      if(card < adventurer || card == baron || card == minion
	 || card == tribute || card == ambassador || card == cutpurse ||
	 card == embargo || card == salvager || card == sea_hag || 
	 card == treasure_map) continue;
      for(i = 0; i < numSelected; i++) {
	if(k[i] == card) {
	  used = 1;
	  break;
	}
      }
      if(used == 1) continue;
      k[numSelected] = card;
      numSelected++;
    }

    /* If flag is set, make (likely) two kingdomCards match */
    if(kCardSameSeed == 1){
      firstCard = floor(Random() * NUM_K_CARDS);
      secondCard = floor(Random() * NUM_K_CARDS);
      k[firstCard] = k[secondCard];
    }

    /* Or, if flag is set, make one of the kingdomCards (likely) out of Range */
    if(kCardOutOfRangeSeed == 1){
      firstCard = floor(Random() * NUM_K_CARDS);
      k[firstCard] = floor(Random() * 1000);
    }
    
    /* Initialize new game... if it fails... */
    if(initializeGame(numPlayers, k, seed, &G) == -1){
      /* and number of players is out of range, then it's expected */
      if(numPlayers < 2 || numPlayers > 4){
	expectedFailures++;
	unexpectedFailure = 0;
      }
      /* or if two kingdom Cards match, then it's expected */
      for(i = 0; i < NUM_K_CARDS; i++){
	for(m = 0; m < NUM_K_CARDS; m++){
	  if(k[i] == k[m] && i != m){
	    expectedFailures++;
	    unexpectedFailure = 0;
	  }
	}
      }
      /* or if one of the kingdom Cards is out of range, then it's expected */
      for(i = 0; i < NUM_K_CARDS; i++){
	if(k[i] < adventurer || k[i] > treasure_map){
	  expectedFailures++;
	  unexpectedFailure = 0;
	}
      }
      /* or if none of those are true, then it's UNEXPECTED */
      if(unexpectedFailure == 1){
	printf("\n***Initialize Game Failed.***\nNumber of Players: %d\n"
	       "Seed: %d\n", numPlayers, seed);
	for(i = 0; i < NUM_K_CARDS; i++){
	  printf("Kingdom Card %d: %s\n", i, getCardName(k[i]));
	  numFailed++;
	}
      }
    }
  }
  
  /* Print Results */
  printf("***TESTS COMPLETE***\n"
	 "Number of tests with valid input passed: %d\n"
	 "Number of expected failures that passed: %d\n"
	 "Number of Failed Tests: %d\n\n", 
	 (2000 - numFailed - expectedFailures), expectedFailures, numFailed);
  return 0;
}
